package com.yoo.ons.function.home.viewmodel

import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.paging.DataSource
import androidx.paging.PagedList
import androidx.paging.toLiveData
import com.framework.network.remote.NetworkObserver
import com.framework.network.remote.endRequest
import com.framework.network.remote.error
import com.framework.network.remote.requestObserver
import com.framework.network.remote.startRequest
import com.framework.network.remote.success
import com.yoo.chat.kit.model.ActionModel
import com.yoo.ons.base.BaseVMViewModel
import com.yoo.ons.base.HttpRequestListener
import com.yoo.ons.base.Request
import com.yoo.ons.base.adpater.Cell
import com.yoo.ons.base.adpater.ID_EMPTY
import com.yoo.ons.base.adpater.ID_ERROR
import com.yoo.ons.base.adpater.ID_MORE_LOADING
import com.yoo.ons.base.adpater.ID_NO_MORE
import com.yoo.ons.base.adpater.LoadStatus
import com.yoo.ons.base.adpater.PAGE_INITIAL
import com.yoo.ons.base.adpater.PageDataSource
import com.yoo.ons.base.adpater.add
import com.yoo.ons.base.adpater.addAll
import com.yoo.ons.base.adpater.isRefreshing
import com.yoo.ons.base.adpater.mutablePutAll
import com.yoo.ons.base.adpater.remove
import com.yoo.ons.base.adpater.safelySubList
import com.yoo.ons.base.adpater.superProcessCell
import com.yoo.ons.model.HomeListModel
import com.yoo.ons.model.LoginResultModel
import com.yoo.ons.model.MatchLikeModel
import com.yoo.ons.util.runOnUIThread
import com.yoo.ons.util.runOnWorkThread
import kotlin.math.max
import kotlin.math.min

data class HomeState(
    val page: Int = PAGE_INITIAL,
    val list: List<String> = listOf(),//保存所有的ID
    val data: Map<String, HomeListModel.MatchIndexBean> = mapOf(),//数据存储
    val loading: LoadStatus = LoadStatus.IDLE
) {
    companion object {
        const val ID_DAILY_INCOME_LIST = "ID_DAILY_INCOME_LIST"
    }
}

class HomeViewModel : BaseVMViewModel() {

    private var listener: HttpRequestListener<HomeListModel>? = null
    fun setListener(listener: HttpRequestListener<HomeListModel>) {
        this.listener = listener
    }


    val loading = MutableLiveData<LoadStatus>()
    var indexState = HomeState()
    var indexDataSource: PageDataSource? = null
    val dataAllList = indexDataSoureFactory()
        .toLiveData(
            pageSize = 30,
            boundaryCallback = object : PagedList.BoundaryCallback<Cell>() {
                override fun onItemAtEndLoaded(itemAtEnd: Cell) {
                    if (ID_MORE_LOADING == itemAtEnd.id) {
                        //reqIndexList(false)
                        Log.i("HomeViewModel", "indexDataSoureFactory")
                    }
                }
            }
        )

    //请求数据
    fun reqIndexList(initial: Boolean) {
        runOnWorkThread { internalRequestIndexList(initial) }
    }


    private fun internalRequestIndexList(
        initial: Boolean
    ) {
        if (indexState.loading.isRefreshing()) return
        reducing(initial)
        request(listener, request = object : Request {
            override fun request(map: HashMap<String, Any>, requestEndListener: (() -> Unit?)?) {
                apiService?.postHomeList(map)?.requestObserver(
                    NetworkObserver<HomeListModel>().startRequest {
                        listener?.startRequest(it)
                    }.success {
                        Log.i("HomeViewModel", "${it?.homepageList?.size}")
                        //返回结果
                        reducingResult(initial, it?.homepageList ?: listOf())
                    }.error {
                        reducingError(initial)
                    }.endRequest {
                        listener?.endRequest()
                    }
                )

            }

        })

    }

    private fun reducingResult(initial: Boolean, data: List<HomeListModel.MatchIndexBean>) {
        if (initial) {
            if (data.isNullOrEmpty()) {
                indexState = indexState.copy(
                    page = PAGE_INITIAL,
                    list = listOf(ID_EMPTY),
                    loading = LoadStatus.SUCCESS
                )
            } else {
                //不为空的情况
                val actuallyFetchOver = data.size < 30
                var preList = data.map { it.friendUserCode.toString() }

                preList =
                    if (actuallyFetchOver) preList.add(ID_NO_MORE) else preList.add(ID_MORE_LOADING)

                indexState = indexState.let {
                    it.copy(
                        page = PAGE_INITIAL,
                        list = preList,
                        data = it.data.mutablePutAll(data.map {
                            Pair(
                                it.friendUserCode.toString(),
                                it
                            )
                        }),
                        loading = LoadStatus.SUCCESS
                    )
                }
            }
        } else {
            indexState = if (data.isEmpty()) {
                indexState.let {
                    it.copy(
                        page = PAGE_INITIAL,
                        list = it.list.remove(ID_MORE_LOADING).add(ID_NO_MORE)
                    )
                }
            } else {
                val actuallyFetchOver = data.size < 30

                indexState.let {
                    it.copy(
                        page = it.page + 1,
                        list = it.list.remove(ID_MORE_LOADING).addAll(data.map {
                            it.friendUserCode.toString()
                        }).let {
                            if (actuallyFetchOver) it.add(ID_NO_MORE) else it.add(ID_MORE_LOADING)
                        },
                        data = it.data.mutablePutAll(
                            data.map {
                                Pair(it.friendUserCode.toString(), it)
                            }
                        )
                    )
                }
            }
        }
        Log.i("IndexFragment", "IndexViewModel reducingResult $indexState")
        notifyStateInvalidate()
    }

    private fun reducing(initial: Boolean) {
        if (initial) {
            indexState = indexState.copy(loading = LoadStatus.LOADING)
            loading.postValue(indexState.loading)
        }
    }

    private fun reducingError(initial: Boolean) {
        indexState = if (initial) {
            indexState.copy(
                list = listOf(ID_ERROR),
                loading = LoadStatus.FAILURE
            )
        } else {
            indexState.let {
                it.copy(
                    list = it.list.add(ID_NO_MORE),
                    loading = LoadStatus.FAILURE
                )
            }
        }
        notifyStateInvalidate()
    }

    private fun notifyStateInvalidate() {
        indexDataSource?.invalidate()
        if (loading.value != indexState.loading) {
            runOnUIThread {
                loading.value = indexState.loading
            }
        }
    }

    private fun indexDataSoureFactory(): DataSource.Factory<Int, Cell> =
        object : DataSource.Factory<Int, Cell>() {
            override fun create(): DataSource<Int, Cell> {
                return object : PageDataSource() {
                    override fun totalCount(): Int {
                        return indexState.list.size
                    }

                    override fun loadRange(start: Int, count: Int): List<Cell?> {
                        val list = indexState.list
                        return list.safelySubList(max(0, start), min(list.size, start + count))
                            .map {
                                superProcessCell(it)
                                    ?: Cell(
                                        ItemType.HomeListData,
                                        it,
                                        extra = indexState.data[it]
                                    )
                            }
                    }
                }.also {
                    indexDataSource = it
                }
            }
        }

    fun postUserLike(
        direction: String,
        userCodeFriend: String,
        callback: (MatchLikeModel?) -> Unit
    ) {
        val listener = object : HttpRequestListener<MatchLikeModel>() {
            override fun addRequestParams(params: HashMap<String, Any>) {
                params["likeType"] = if (direction == "Right") 1 else 4
                params["userCodeFriend"] = userCodeFriend
            }

            override fun success(t: MatchLikeModel?) {

            }
        }
        request(listener, request = object : Request {
            override fun request(map: HashMap<String, Any>, requestEndListener: (() -> Unit?)?) {
                apiService?.postUserAddWlm(map)?.requestObserver(
                    NetworkObserver<MatchLikeModel>().startRequest {
                        listener.startRequest(it)
                    }.success {
                        callback.invoke(it)
                    }.error {
                        listener.error(it)
                    }.endRequest {
                        listener.endRequest()
                    }
                )
            }

        })
    }

    val clickFcLiveData = MutableLiveData<Boolean>()
    fun clickHomeFc(isCLickFc: Boolean) {
        //点击了首页划卡上和首页信息弹窗上的fc按钮，卡片需要走like逻辑
        clickFcLiveData.value = isCLickFc
    }

}

//class HomeViewModelModelFactory(private val listener: HttpRequestListener<HomeListModel>) : ViewModelProvider.Factory {
//    override fun <T : ViewModel> create(modelClass: Class<T>): T {
//        if (modelClass.isAssignableFrom(HomeViewModel::class.java)) {
//            return HomeViewModel(listener) as T
//        }
//        //noinspection unchecked
//        throw IllegalArgumentException("Unknown ViewModel class")
//    }
//}
